package server;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


/**
 * TestPoints are generated, when the Server is in the REFPOINTSAMPLER mode.
 * 
 * @author nemi
 *
 */
public class TestPoint extends SinglePoint {
	public TestPoint(ArrayList<DataSet> samples) {
		super("testpoint"+String.valueOf(count));
		this.samples.addAll(samples);
		this.calculateMeanValues();
		nearRSSIRefPoints=new ArrayList<RefPointDistance>();
		nearLQIRefPoints=new ArrayList<RefPointDistance>();
		nearPLRRefPoints=new ArrayList<RefPointDistance>();
	}
	
	private static int count=0;
	public String ownSpotID="testID";
	public ArrayList<RefPointDistance> nearRSSIRefPoints;
	public ArrayList<RefPointDistance> nearLQIRefPoints;
	public ArrayList<RefPointDistance> nearPLRRefPoints;
	
	/**
	 * simply determines the nearest ReferencePoint according to the given metric
	 * @param metric the metric which should be used
	 * @return the nearest ReferencePoint
	 */
	public RefPointDistance getNearestX(String metric){
		//System.out.println("getNearestX()");
		if(metric.equals("RSSI")){
			return nearRSSIRefPoints.get(0);
		}
		else if(metric.equals("LQI")){
			return nearLQIRefPoints.get(0);
		}
		else if(metric.equals("PLR")){
			return nearPLRRefPoints.get(0);
		}
		return null;
	}
	
	/**
	 * more sophisticated positioning. Takes into account the topCount "nearest" ReferencePoints of the given metrics and
	 * calculates a ranking. The leader of this ranking should be the best matching ReferencePoint.
	 * @param topCount number of ReferencePoints from each metric that should be taken into account
	 * @param metrics metrics that should be used
	 * @return the best matching ReferencePoint
	 */
	public ReferencePoint getNearestDoRanking(int topCount, Set<Metric> metrics){
		
		Map<RefPointDistance,Integer> ranking=new HashMap<RefPointDistance,Integer>();
		
		ReferencePoint result=null;
		
		for(int i=0;i<topCount && i< nearRSSIRefPoints.size();i++){
			if(metrics.contains(Metric.RSSI)){
				if(ranking.containsKey(nearRSSIRefPoints.get(i))){
					ranking.put(nearRSSIRefPoints.get(i), ranking.get(nearRSSIRefPoints)+Integer.valueOf(topCount-i));
				}
			}
			if(metrics.contains(Metric.LQI)){
				if(ranking.containsKey(nearLQIRefPoints.get(i))){
					ranking.put(nearLQIRefPoints.get(i), ranking.get(nearLQIRefPoints)+Integer.valueOf(topCount-i));
				}
			}
			if(metrics.contains(Metric.PLR)){
				if(ranking.containsKey(nearPLRRefPoints.get(i))){
					ranking.put(nearPLRRefPoints.get(i), ranking.get(nearPLRRefPoints)+Integer.valueOf(topCount-i));
				}
			}
		}
		
		int max=0;
		for(RefPointDistance ref:ranking.keySet()){
			if(ranking.get(ref)>max){
				max=ranking.get(ref);
				result=ref.aRefPoint;
			}
		}
		
		return result;
	}

}
